home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / Miro_Downloader.exe / iconcache.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2007-11-12  |  9.0 KB  |  333 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. import item
  5. import os
  6. import threading
  7. import httpclient
  8. from fasttypes import LinkedList
  9. from eventloop import asIdle, addIdle, addTimeout
  10. from download_utils import nextFreeFilename, getFileURLPath
  11. from util import unicodify, call_command
  12. from platformutils import unicodeToFilename
  13. import config
  14. import prefs
  15. import time
  16. import views
  17. import random
  18. import imageresize
  19. RUNNING_MAX = 3
  20.  
  21. def clearOrphans():
  22.     knownIcons = set()
  23.     for item in views.items:
  24.         if item.iconCache and item.iconCache.filename:
  25.             knownIcons.add(os.path.normcase(item.iconCache.filename))
  26.             for resized in item.iconCache.resized_filenames.values():
  27.                 knownIcons.add(os.path.normcase(resized))
  28.             
  29.     
  30.     for feed in views.feeds:
  31.         if feed.iconCache and feed.iconCache.filename:
  32.             knownIcons.add(os.path.normcase(feed.iconCache.filename))
  33.             for resized in feed.iconCache.resized_filenames.values():
  34.                 knownIcons.add(os.path.normcase(resized))
  35.             
  36.     
  37.     cachedir = config.get(prefs.ICON_CACHE_DIRECTORY)
  38.  
  39.  
  40. class IconCacheUpdater:
  41.     
  42.     def __init__(self):
  43.         self.idle = LinkedList()
  44.         self.vital = LinkedList()
  45.         self.runningCount = 0
  46.         self.inShutdown = False
  47.  
  48.     
  49.     def requestUpdate(self, item, is_vital = False):
  50.         if is_vital:
  51.             item.dbItem.confirmDBThread()
  52.             if item.filename and os.access(item.filename, os.R_OK):
  53.                 is_vital = False
  54.             
  55.         
  56.         if self.runningCount < RUNNING_MAX:
  57.             addIdle(item.requestIcon, 'Icon Request')
  58.             self.runningCount += 1
  59.         elif is_vital:
  60.             self.vital.prepend(item)
  61.         else:
  62.             self.idle.prepend(item)
  63.  
  64.     requestUpdate = asIdle(requestUpdate)
  65.     
  66.     def updateFinished(self):
  67.         if self.inShutdown:
  68.             self.runningCount -= 1
  69.             return None
  70.         
  71.         if len(self.vital) > 0:
  72.             item = self.vital.pop()
  73.         elif len(self.idle) > 0:
  74.             item = self.idle.pop()
  75.         else:
  76.             self.runningCount -= 1
  77.             return None
  78.         addIdle(item.requestIcon, 'Icon Request')
  79.  
  80.     
  81.     def clearVital(self):
  82.         self.vital = LinkedList()
  83.  
  84.     clearVital = asIdle(clearVital)
  85.     
  86.     def shutdown(self):
  87.         self.inShutdown = True
  88.  
  89.     shutdown = asIdle(shutdown)
  90.  
  91. iconCacheUpdater = IconCacheUpdater()
  92.  
  93. class IconCache:
  94.     
  95.     def __init__(self, dbItem, is_vital = False):
  96.         self.etag = None
  97.         self.modified = None
  98.         self.filename = None
  99.         self.resized_filenames = { }
  100.         self.url = None
  101.         self.updated = False
  102.         self.updating = False
  103.         self.needsUpdate = False
  104.         self.dbItem = dbItem
  105.         self.removed = False
  106.         self.requestUpdate(is_vital = is_vital)
  107.  
  108.     
  109.     def remove(self):
  110.         self.removed = True
  111.         self._removeFile(self.filename)
  112.         imageresize.removeResizedFiles(self.resized_filenames)
  113.  
  114.     
  115.     def _removeFile(self, filename):
  116.         
  117.         try:
  118.             os.remove(filename)
  119.         except:
  120.             pass
  121.  
  122.  
  123.     
  124.     def errorCallback(self, url, error = None):
  125.         self.dbItem.confirmDBThread()
  126.         if self.removed:
  127.             iconCacheUpdater.updateFinished()
  128.             return None
  129.         
  130.         if self.url != url:
  131.             self.url = url
  132.             self.etag = None
  133.             self.modified = None
  134.             self.dbItem.signalChange()
  135.         
  136.         self.updating = False
  137.         if self.needsUpdate:
  138.             self.needsUpdate = False
  139.             self.requestUpdate()
  140.         elif error is not None:
  141.             addTimeout(3600, self.requestUpdate, 'Thumbnail request for %s' % url)
  142.         else:
  143.             self.updated = True
  144.         iconCacheUpdater.updateFinished()
  145.  
  146.     
  147.     def updateIconCache(self, url, info):
  148.         self.dbItem.confirmDBThread()
  149.         if self.removed:
  150.             iconCacheUpdater.updateFinished()
  151.             return None
  152.         
  153.         needsSave = False
  154.         needsChange = False
  155.         if (info == None or info['status'] != 304) and info['status'] != 200:
  156.             self.errorCallback(url)
  157.             return None
  158.         
  159.         
  160.         try:
  161.             if info['status'] == 304:
  162.                 self.updated = True
  163.                 return None
  164.             
  165.             needsChange = True
  166.             if self.filename and not os.access(self.filename, os.R_OK | os.W_OK):
  167.                 self.filename = None
  168.                 seedsSave = True
  169.             
  170.             cachedir = config.get(prefs.ICON_CACHE_DIRECTORY)
  171.             
  172.             try:
  173.                 os.makedirs(cachedir)
  174.             except:
  175.                 pass
  176.  
  177.             
  178.             try:
  179.                 if self.filename:
  180.                     tmp_filename = self.filename + '.part'
  181.                 else:
  182.                     tmp_filename = os.path.join(cachedir, info['filename']) + '.part'
  183.                 tmp_filename = nextFreeFilename(tmp_filename)
  184.                 output = file(tmp_filename, 'wb')
  185.                 output.write(info['body'])
  186.                 output.close()
  187.             except IOError:
  188.                 
  189.                 try:
  190.                     os.remove(tmp_filename)
  191.                 except:
  192.                     pass
  193.  
  194.                 return None
  195.  
  196.             if self.filename == None:
  197.                 parts = unicodify(info['filename']).split('.')
  198.                 uid = u'%08d' % (random.randint(0, 99999999),)
  199.                 if len(parts) == 1:
  200.                     parts.append(uid)
  201.                 else:
  202.                     parts[-1:-1] = [
  203.                         uid]
  204.                 self.filename = u'.'.join(parts)
  205.                 self.filename = unicodeToFilename(self.filename, cachedir)
  206.                 self.filename = os.path.join(cachedir, self.filename)
  207.                 self.filename = nextFreeFilename(self.filename)
  208.                 needsSave = True
  209.             
  210.             self._removeFile(self.filename)
  211.             
  212.             try:
  213.                 os.rename(tmp_filename, self.filename)
  214.             except:
  215.                 self.filename = None
  216.                 needsSave = True
  217.  
  218.             self.resizeIcon()
  219.             if info.has_key('etag'):
  220.                 etag = unicodify(info['etag'])
  221.             else:
  222.                 etag = None
  223.             if info.has_key('modified'):
  224.                 modified = unicodify(info['modified'])
  225.             else:
  226.                 modified = None
  227.             if self.etag != etag:
  228.                 needsSave = True
  229.                 self.etag = etag
  230.             
  231.             if self.modified != modified:
  232.                 needsSave = True
  233.                 self.modified = modified
  234.             
  235.             if self.url != url:
  236.                 needsSave = True
  237.                 self.url = url
  238.             
  239.             self.updated = True
  240.         finally:
  241.             if needsChange:
  242.                 self.dbItem.signalChange(needsSave = needsSave)
  243.             
  244.             self.updating = False
  245.             if self.needsUpdate:
  246.                 self.needsUpdate = False
  247.                 self.requestUpdate()
  248.             
  249.             iconCacheUpdater.updateFinished()
  250.  
  251.  
  252.     
  253.     def requestIcon(self):
  254.         if self.removed:
  255.             iconCacheUpdater.updateFinished()
  256.             return None
  257.         
  258.         self.dbItem.confirmDBThread()
  259.         if self.updating:
  260.             self.needsUpdate = True
  261.             iconCacheUpdater.updateFinished()
  262.             return None
  263.         
  264.         
  265.         try:
  266.             url = self.dbItem.getThumbnailURL()
  267.         except:
  268.             url = self.url
  269.  
  270.         if self.updated and url == self.url:
  271.             iconCacheUpdater.updateFinished()
  272.             return None
  273.         
  274.         self.updating = True
  275.         if url is None and url.startswith(u'/') or url.startswith(u'file://'):
  276.             self.errorCallback(url)
  277.             return None
  278.         
  279.         if url == self.url and self.filename and os.access(self.filename, os.R_OK):
  280.             None(None, ((httpclient.grabURL, url), (lambda info: self.updateIconCache(url, info))), (lambda error: self.errorCallback(url, error)), etag = self.etag, modified = self.modified)
  281.         else:
  282.             None(None, ((httpclient.grabURL, url), (lambda info: self.updateIconCache(url, info))), (lambda error: self.errorCallback(url, error)))
  283.  
  284.     
  285.     def requestUpdate(self, is_vital = False):
  286.         if hasattr(self, 'updating') and hasattr(self, 'dbItem'):
  287.             if self.removed:
  288.                 return None
  289.             
  290.             iconCacheUpdater.requestUpdate(self, is_vital = is_vital)
  291.         
  292.  
  293.     
  294.     def onRestore(self):
  295.         self.removed = False
  296.         self.updated = False
  297.         self.updating = False
  298.         self.needsUpdate = False
  299.         self.requestUpdate()
  300.  
  301.     
  302.     def isValid(self):
  303.         self.dbItem.confirmDBThread()
  304.         if self.filename is not None:
  305.             pass
  306.         return os.path.exists(self.filename)
  307.  
  308.     
  309.     def getFilename(self):
  310.         self.dbItem.confirmDBThread()
  311.         if self.url and self.url.startswith(u'file://'):
  312.             return getFileURLPath(self.url)
  313.         elif self.url and self.url.startswith(u'/'):
  314.             return self.url
  315.         else:
  316.             return self.filename
  317.  
  318.     
  319.     def getResizedFilename(self, width, height):
  320.         
  321.         try:
  322.             return imageresize.getImage(self.resized_filenames, width, height)
  323.         except KeyError:
  324.             return self.getFilename()
  325.  
  326.  
  327.     
  328.     def resizeIcon(self):
  329.         imageresize.removeResizedFiles(self.resized_filenames)
  330.         self.resized_filenames = imageresize.multiResizeImage(self.filename, self.dbItem.ICON_CACHE_SIZES)
  331.  
  332.  
  333.